﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

/*For observable collection */
using System.Collections.ObjectModel;

using GasData;

/* Threading */
/* Synchronized methods */
using System.Threading;
using System.Runtime.CompilerServices;

using System.IO;

namespace WPF_DataLogger
{
    public partial class BTDecoder : PackDecoder
    {
        public BTDecoder()
        {
            decoder_type = DecoderType.BlueTooth;
            FormatPacket();
        }

        public BTDecoder(byte[] packet)
        {
            if (packet != null)
            {
                CopyPacket(packet);

                decoder_type = DecoderType.BlueTooth;
            }

            FormatPacket();
        }

        public override double GetTemp()
        {
            return 0.0;
        }

        public override double GetHumid()
        {
            return 0.0;
        }

        public override int GetGasNum()
        {
            return _packet[gas_num_pos] - '0';
        }

        public override bool IsHeaderCorrect
        {
            get
            {
                for (int i = 0; i < preamble_len && i < preamble_pattern.Length; i++)
                {
                    if (_packet[i] != preamble_pattern[i])
                        return false;
                }

                //Next check the number of sensors is 5;
                if (_packet[gas_num_pos] != BT_SENSOR_NUM)
                    return false;

                return true;
            }
        }

        public override bool IsTailCorrect
        {
            get
            {
                for (int i = 0; i < this.PacketTailLength && 
                    i < tail_pattern.Length; i++)
                {
                    if(_packet[i + BT_TAIL_START_POS] != tail_pattern[i])
                        return false;
                }

                return true;
            }
        }

        public override int HeaderLength
        {
            get
            {
                return gas_base_pos;
            }
        }

        public override int SensorFieldLength
        {
            get
            {
                if (_packet != null)
                {
                    return (_packet[gas_num_pos] - '0' ) * 3;
                }
                else
                {
                    throw new System.NullReferenceException("decoder: data packet is null");
                }
            }
        }

        public override int PacketTailLength
        {
            get
            {
                return 4;
            }
        }

        public override int PackPayloadLen
        {
            get
            {
                return SensorFieldLength;
            }
        }

        public override int PreambleLength
        {
            get
            {
                return preamble_len;
            }
        }


        public override ObservableCollection<GasInfo> GetGasList(List<string> gas_name_list, SensorFamily family)
        {
            ObservableCollection<GasInfo> ret = new ObservableCollection<GasInfo>();
            int next_gas_pos = gas_base_pos;

            if (_packet == null)
            {
                throw new NullReferenceException("Bluetooth: _packet is null.");               
            }

            if (gas_name_list == null)
            {
                throw new NullReferenceException("Bluetooth: Gas name list null");
            }

            for (int i = 0; i < _packet[gas_num_pos] && i < gas_name_list.Count;
              i++,next_gas_pos += BT_GAS_LENGTH)
            {
                int gas_value_int = BTGetOneSensorVal(next_gas_pos);

                using (FileStream debug_stream = new FileStream(".\\btint.txt",FileMode.Append))
                {
                    using (StreamWriter debug_writer = new StreamWriter(debug_stream)){
                        debug_writer.WriteLine(gas_value_int);
                    }
                }

                double next_gas_value = GetGasValue(gas_value_int,gas_name_list[i],family);

                GasInfo new_gas_info = new GasInfo();

                new_gas_info.Gas_name = gas_name_list[i];
                new_gas_info.Cur_val = (double)Decimal.Round((decimal)next_gas_value,5);

                ret.Add(new_gas_info);
            }

            return ret;

        }

        private int BTGetOneSensorVal(int gas_base_idx)
        {
            return (_packet[gas_base_idx] - '0') * 100 + (_packet[gas_base_idx + 1] - '0') * 10 +
                (_packet[gas_base_idx + 2] - '0');
        }


        public override bool IsPreambleData(byte data)
        {
            //TODO
            //Add the preamble data checking here

            return data == preamble_pattern[0];
        }

        public override bool IsPreambleEnd(byte data)
        {
            //TODO
            //Add the preamble end checking here;
            return data == preamble_pattern[preamble_pattern.Length - 1];
        }

        protected override void FormatPacket()
        {
            temp_pos = BT_TEMP_POS;
            humid_pos = BT_HUMID_POS;
            gps_time_hour = BT_GPS_TIME_HOUR;
            gps_time_min = BT_GPS_TIME_MIN;
            gps_time_sec = BT_GPS_TIME_SEC;
            gps_longitude = BT_GPS_LONGITUDE;
            gps_latitude = BT_GPS_LATITUDE;
            node_id_pos = BT_NODE_ID_POS;
            gas_num_pos = BT_GAS_NUM_POS;
            gas_base_pos = BT_GAS_BASE_POS;
            preamble_len = BT_PREAMBLE_LEN;
            pack_len_pos = BT_PACK_LEN_POS;
            _adc_max_value = BT_ADC_MAX_VALUE;
            pack_type_pos = BT_PACK_TYPE_POS;
            preamble_pattern = new int []{ 0x30, 0x30};
            tail_pattern = new int [] {0x30, 0x31, 0x30, 0x31};

        }

        const int BT_TEMP_POS = 0;
        const int BT_HUMID_POS = 0;
        const int BT_GPS_TIME_HOUR = 0;
        const int BT_GPS_TIME_MIN = 0;
        const int BT_GPS_TIME_SEC = 0;
        const int BT_GPS_LONGITUDE = 0;
        const int BT_GPS_LATITUDE = 0;
        const int BT_PREAMBLE_LEN = 2;
        const int BT_PACK_LEN_POS = 0;
        const int BT_NODE_ID_POS = 2;
        const int BT_GAS_NUM_POS = 2;
        const int BT_GAS_BASE_POS = 3;
        const int BT_ADC_MAX_VALUE = 255;
        const int BT_PACK_TYPE_POS = 0;
        const int BT_GAS_LENGTH = 3;
        const int BT_TAIL_START_POS = 18;

        const int INIT_SHIFT_BITS = 0;
        const int SHIFT_STEP = 2;

        const int BT_SENSOR_NUM = 0x35; //ASCII code for '5'
    }

    
}
